package com.cash.channel.web.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.JSONToken;
import com.google.common.collect.Maps;
import net.sf.json.util.JSONTokener;
import org.apache.commons.collections.MapUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class HttpRequestUtils {

    private static Logger logger = LoggerFactory.getLogger(HttpRequestUtils.class);    //日志记录

    /**
     * post请求
     *
     * @param url       url地址
     * @param jsonParam 参数
     * @return
     */
    public static JSONObject httpPost(String url, JSON jsonParam) {
        //post请求返回结果
        //  DefaultHttpClient httpClient = new DefaultHttpClient();
        CloseableHttpClient httpClient = HttpClients.createDefault();
        JSONObject jsonResult = null;
        HttpPost method = new HttpPost(url);
        try {
            if (null != jsonParam) {
                //解决中文乱码问题
                StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");
                entity.setContentEncoding("UTF-8");
                entity.setContentType("application/json");
                method.setEntity(entity);
            }
            logger.info("post请求参数:" + url + " ===" + jsonParam.toString());
            HttpResponse result = httpClient.execute(method);
            url = URLDecoder.decode(url, "UTF-8");
            /**请求发送成功，并得到响应**/
            if (result.getStatusLine().getStatusCode() == 200) {
                String str = "";
                try {
                    /**读取服务器返回过来的json字符串数据**/
                    str = EntityUtils.toString(result.getEntity());
                    logger.info("post请求提交:" + str);
                    /**把json字符串转换成json对象**/
                    jsonResult = JSON.parseObject(str);
                } catch (Exception e) {
                    logger.error("post请求提交失败:" + url, e);
                }
            } else {
                String str = EntityUtils.toString(result.getEntity());
                jsonResult = JSON.parseObject(str);
                logger.error("post请求提交失败:" + result.getStatusLine());
            }
        } catch (IOException e) {
            logger.error("post请求提交失败:" + url, e);
        }
        return jsonResult;
    }


    /**
     * 发送get请求
     *
     * @param url 路径
     * @return
     */
    public static JSONObject httpGet(String url) {
        //get请求返回结果
        JSONObject jsonResult = null;
        try {
            //  DefaultHttpClient client = new DefaultHttpClient();
            CloseableHttpClient client = HttpClients.createDefault();
            //发送get请求
            HttpGet request = new HttpGet(url);
            HttpResponse response = client.execute(request);
            logger.info("get请求参数:" + url);
            /**请求发送成功，并得到响应**/
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                /**读取服务器返回过来的json字符串数据**/
                String strResult = EntityUtils.toString(response.getEntity());
                logger.info("get请求提交:" + strResult);
                /**把json字符串转换成json对象**/
                jsonResult = JSON.parseObject(strResult);
                url = URLDecoder.decode(url, "UTF-8");
            } else {
                logger.error("get请求提交失败:" + response.getStatusLine());
            }
        } catch (IOException e) {
            logger.error("get请求提交失败:" + url, e);
        }
        return jsonResult;
    }

    /**
     * @param url
     * @param headerParams
     * @return json ->json
     * jsonArray  ->map
     */
    public static Map<String, Object> httpGet(String url, Map<String, String> headerParams) {
        //get请求返回结果
        JSONObject jsonResult = null;
        try {
            logger.info("get请求参数:" + url);
            logger.info("header:" + headerParams);
            //  DefaultHttpClient client = new DefaultHttpClient();
            CloseableHttpClient client = HttpClients.createDefault();
            //发送get请求
            HttpGet request = new HttpGet(url);
            if (MapUtils.isNotEmpty(headerParams)) {
                Iterator headerIter = headerParams.entrySet().iterator();
                while (headerIter.hasNext()) {
                    Map.Entry<String, String> elem = (Map.Entry<String, String>) headerIter.next();
                    request.setHeader(elem.getKey(), elem.getValue());
                }
            }
            HttpResponse response = client.execute(request);

            /**请求发送成功，并得到响应**/
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                /**读取服务器返回过来的json字符串数据**/
                String strResult = EntityUtils.toString(response.getEntity());

                logger.info("get请求提交:" + strResult);
                /**把json字符串转换成json对象**/
                if (null != strResult) {
                    jsonResult = JSON.parseObject(strResult);
                }
                url = URLDecoder.decode(url, "UTF-8");
            } else {
                logger.error("get请求提交失败:" + response.getStatusLine());
            }
        } catch (IOException e) {
            logger.error("get请求提交失败:" + url, e);
        }
        return jsonResult;
    }

    /**
     * post请求
     *
     * @param url url地址
     * @return
     */
    public static JSONObject httpPost(String url, Map<String, Object> params, Map<String, File> files) {
        //post请求返回结果
        CloseableHttpClient httpClient = HttpClients.createDefault();
        JSONObject jsonResult = null;
        HttpPost method = new HttpPost(url);
        try {
            if (null != params) {
                //解决中文乱码问题
                MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
                for (Map.Entry entry : params.entrySet()) {
//                    if (ClassUtils.isAssignable(entry.getValue().getClass(),String.class)){
                    ContentType strContent = ContentType.create("text/plain", Charset.forName("UTF-8"));
                    entityBuilder.addTextBody((String) entry.getKey(), String.valueOf(entry.getValue()), strContent);
//                    }
                }
                for (Map.Entry<String, File> file : files.entrySet()) {
                    entityBuilder.addBinaryBody(file.getKey(), file.getValue(), ContentType.DEFAULT_BINARY, file.getValue().getName());
                }
                method.setEntity(entityBuilder.build());
            }
            HttpResponse result = httpClient.execute(method);
            url = URLDecoder.decode(url, "UTF-8");
            /**请求发送成功，并得到响应**/
            if (result.getStatusLine().getStatusCode() == 200) {
                String str = "";
                try {
                    /**读取服务器返回过来的json字符串数据**/
                    str = EntityUtils.toString(result.getEntity(), "utf-8");
                    /**把json字符串转换成json对象**/
                    jsonResult = JSON.parseObject(str);
                } catch (Exception e) {
                    logger.error("post请求提交失败:" + url, e);
                }
            } else {
                String str = EntityUtils.toString(result.getEntity());
                jsonResult = JSON.parseObject(str);
                logger.error("post请求提交失败:" + result.getStatusLine());
            }
        } catch (IOException e) {
            logger.error("post请求提交失败:" + url, e);
        }
        return jsonResult;
    }

    public static JSONObject httpPost(String url, Map<String, Object> map, String charset, Map<String, String> headerParams) {
        CloseableHttpClient httpClient = null;
        HttpPost httpPost = null;
        JSONObject jsonResult = null;
        String result = null;
        try {
            httpClient = HttpClients.createDefault();
            httpPost = new HttpPost(url);
            //设置参数
            List<NameValuePair> list = new ArrayList<NameValuePair>();
            if (MapUtils.isNotEmpty(map)) {
                Iterator iterator = map.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, String> elem = (Map.Entry<String, String>) iterator.next();
                    list.add(new BasicNameValuePair(elem.getKey(), elem.getValue()));
                }
            }
            if (MapUtils.isNotEmpty(headerParams)) {
                Iterator headerIter = headerParams.entrySet().iterator();
                while (headerIter.hasNext()) {
                    Map.Entry<String, String> elem = (Map.Entry<String, String>) headerIter.next();
                    httpPost.setHeader(elem.getKey(), elem.getValue());
                }
            }
            if (list.size() > 0) {
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, charset);
                httpPost.setEntity(entity);
            }
            HttpResponse response = httpClient.execute(httpPost);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                HttpEntity resEntity = response.getEntity();
                if (resEntity != null) {
                    result = EntityUtils.toString(resEntity, charset);
                    jsonResult = JSON.parseObject(result);
                }
            } else {
                logger.error("post请求提交失败:" + url);
                logger.info("header:" + headerParams);
                logger.info("params:" + map);
                logger.info("statusCode:" + response.getStatusLine());
                HttpEntity resEntity = response.getEntity();
                if (resEntity != null) {
                    result = EntityUtils.toString(resEntity, charset);
                    jsonResult = JSON.parseObject(result);
                    logger.info("message:" + jsonResult);
                    throw new Exception(jsonResult.get("message").toString());
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return jsonResult;
    }

    //获取ip 如果是双层代理  获取到的不是真正的ip
    public static String getIPAddress(HttpServletRequest request) {
        String ip = null;

        //X-Forwarded-For：Squid 服务代理
        String ipAddresses = request.getHeader("X-Forwarded-For");

        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //Proxy-Client-IP：apache 服务代理
            ipAddresses = request.getHeader("Proxy-Client-IP");
        }

        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //WL-Proxy-Client-IP：weblogic 服务代理
            ipAddresses = request.getHeader("WL-Proxy-Client-IP");
        }

        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //HTTP_CLIENT_IP：有些代理服务器
            ipAddresses = request.getHeader("HTTP_CLIENT_IP");
        }

        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //X-Real-IP：nginx服务代理
            ipAddresses = request.getHeader("X-Real-IP");
        }

        //有些网络通过多层代理，那么获取到的ip就会有多个，一般都是通过逗号（,）分割开来，并且第一个ip为客户端的真实IP
        if (ipAddresses != null && ipAddresses.length() != 0) {
            ip = ipAddresses.split(",")[0];
        }

        //还是不能获取到，最后再通过request.getRemoteAddr();获取
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    public static JSONArray httpGetJsonArray(String url, Map<String, String> headerParams) {
        //get请求返回结果
        JSONArray jsonResult = null;
        try {
            logger.info("get请求参数:" + url);
            logger.info("header:" + headerParams);
            //  DefaultHttpClient client = new DefaultHttpClient();
            CloseableHttpClient client = HttpClients.createDefault();
            //发送get请求
            HttpGet request = new HttpGet(url);
            if (MapUtils.isNotEmpty(headerParams)) {
                Iterator headerIter = headerParams.entrySet().iterator();
                while (headerIter.hasNext()) {
                    Map.Entry<String, String> elem = (Map.Entry<String, String>) headerIter.next();
                    request.setHeader(elem.getKey(), elem.getValue());
                }
            }
            HttpResponse response = client.execute(request);

            /**请求发送成功，并得到响应**/
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                /**读取服务器返回过来的json字符串数据**/
                String strResult = EntityUtils.toString(response.getEntity());
                logger.info("get请求提交:" + strResult);
                /**把json字符串转换成json对象**/
                jsonResult = JSON.parseArray(strResult);
                url = URLDecoder.decode(url, "UTF-8");
            } else {
                logger.error("get请求提交失败:" + response.getStatusLine());
            }
        } catch (IOException e) {
            logger.error("get请求提交失败:" + url, e);
        }
        return jsonResult;
    }

    public static InputStream httpPostStream(String url, Map<String, Object> headerParams)throws Exception {
        //get请求返回结果
        InputStream inputStream = null;
        try {
            logger.info("get请求参数:" + url);
            logger.info("header:" + headerParams);
            CloseableHttpClient client = HttpClients.createDefault();
            //发送Post请求
            HttpPost request = new HttpPost(url);
            if (MapUtils.isNotEmpty(headerParams)) {

                    //解决中文乱码问题  解决ContentType的 图片是text/html！！！！！
                    MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
                    for (Map.Entry entry : headerParams.entrySet()) {
                        ContentType strContent = ContentType.create("image/jpeg", Charset.forName("UTF-8"));
                        entityBuilder.addTextBody((String) entry.getKey(), String.valueOf(entry.getValue()), strContent);
                    }

                request.setEntity(entityBuilder.build());

                Iterator headerIter = headerParams.entrySet().iterator();
                while (headerIter.hasNext()) {
                    Map.Entry<String, String> elem = (Map.Entry<String, String>) headerIter.next();
                    request.setHeader(elem.getKey(), elem.getValue().toString());
                }
            }
            HttpResponse response = client.execute(request);
            /**请求发送成功，并得到响应**/
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                inputStream=response.getEntity().getContent();
                 logger.info("r360图片信息........"+response.getEntity().getContentLength()+"||"+response.getEntity().getContentType()+"||"+response.getEntity().isStreaming());
                 url = URLDecoder.decode(url, "UTF-8");
            } else {
                logger.error("post请求提交失败:" + response.getStatusLine());
                if(HttpStatus.SC_FORBIDDEN==response.getStatusLine().getStatusCode()){
                    throw new Exception("禁止访问");
                }else if(HttpStatus.SC_NOT_FOUND ==response.getStatusLine().getStatusCode()){
                    throw new Exception("图片未找到");
                }else if(HttpStatus.SC_GONE==response.getStatusLine().getStatusCode()){
                    throw new Exception("token过期");
                }
            }
        } catch (IOException e) {
            logger.error("post请求提交失败:" + url, e);
            throw e;
        }
        return inputStream;
    }
}
